import { isUndefined, isNull, PagedList, PageParams } from "mmb";
import * as brand_followpb from "../grpc-client/service/brand_follow_pb";
import { jsTimestampToPb, pbTimestampToJs } from "./helper";

import {
  getBgsBrandFollowOpSafely,
  getMetadata,
  getOptionsOfLight,
  wrapperGrpcError,
} from "../grpc-client/grpcAdapter";
import {
  BrandFollow,
  UpsertBrandFollowParams,
  UpdateBrandFollowParams,
  BrandFollowWithBrandAndBrandStat,
} from "./declareTypes"
import { getPub, makeTopicOfPub, wrapToMessage } from "../proxy/nsqProxy";

/****************************************************************************************/
/*                                   brand_follow entity                                */
/****************************************************************************************/
const topicOfUpsertBrandFollow = "upsert-brand_follow";

const BrandFollowPbToObject = (
  pb: brand_followpb.BrandFollowEntity
): BrandFollow => {
  return {
    brandFollowId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followedBrandId: `${pb.getFollowedBrandId()}`,
    followed: pbTimestampToJs(pb.getFollowed()),
    remark: pb.getRemark(),
  };
};

/****************************************************************************************/
/*                                   brand_follow cmd                                   */
/****************************************************************************************/

export const upsertBrandFollowMq = async ({
  userId,
  followedBrandId,
  followed,
}: UpsertBrandFollowParams): Promise<boolean> => {
  return new Promise((resolve, reject) => {
    const topic = makeTopicOfPub(topicOfUpsertBrandFollow)
    const msg = wrapToMessage({
      userId: Number(userId),
      followedBrandId: Number(followedBrandId),
      followed,
    })
    // console.log('publish upsertBrandFollowMq =>', topic ,JSON.stringify(msg))
    getPub().publish(
      topic,
      msg,
      (err) => {
        if (err) {
          // console.log("upsertBrandFollowMq err", err);
          reject(false);
        }
        // console.log("upsertBrandFollowMq success");
        resolve(true);
      }
    );
  });
};

export const upsertBrandFollow = async ({
  userId,
  followedBrandId,
  followed,
}: UpsertBrandFollowParams): Promise<BrandFollow> => {
  const cl = getBgsBrandFollowOpSafely();
  const req = new brand_followpb.UpsertBrandFollowRequest();
  req.setUserId(Number(userId));
  req.setFollowedBrandId(Number(followedBrandId));
  req.setFollowed(jsTimestampToPb(followed));

  return new Promise((resolve, reject) => {
    cl.upsertBrandFollow(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(BrandFollowPbToObject(res.getBrandFollow()!));
      }
    );
  });
};

export const updateBrandFollow = async ({
  brandFollowId,
  remark,
}: UpdateBrandFollowParams): Promise<BrandFollow> => {
  const cl = getBgsBrandFollowOpSafely();
  const req = new brand_followpb.UpdateBrandFollowRequest();

  req.setId(Number(brandFollowId));
  if (!isUndefined(remark)) {
    req.setRemark(remark);
  }

  return new Promise((resolve, reject) => {
    cl.updateBrandFollow(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        resolve(BrandFollowPbToObject(res.getBrandFollow()!));
      }
    );
  });
};

/****************************************************************************************/
/*                                   brand_follow query                                 */
/****************************************************************************************/

export const getBrandFollow = async (
  brandFollowId: string
): Promise<BrandFollow> => {
  const cl = getBgsBrandFollowOpSafely();
  const req = new brand_followpb.GetBrandFollowRequest();

  req.setId(Number(brandFollowId));

  return new Promise((resolve, reject) => {
    cl.getBrandFollow(req, getMetadata(), getOptionsOfLight(), (err, res) => {
      if (!isNull(err)) {
        reject(wrapperGrpcError(err.details));
        return;
      }
      const opRet = res.getOpRet()!;
      if (!opRet.getSuccess()) {
        reject(wrapperGrpcError(opRet.getMsg()));
        return;
      }
      resolve(BrandFollowPbToObject(res.getBrandFollow()!));
    });
  });
};

/****************************************************************************************/
/*                                   brand_follow joins entity                          */
/****************************************************************************************/

const brandFollowWithBrandAndBrandStatPbToObject = (
  pb: brand_followpb.BrandFollowWithBrandAndBrandStatEntity
): BrandFollowWithBrandAndBrandStat => {
  return {
    // brand_follow
    brandFollowId: `${pb.getId()}`,
    userId: `${pb.getUserId()}`,
    followedBrandId: `${pb.getFollowedBrandId()}`,
    followed: pbTimestampToJs(pb.getFollowed()),
    remark: pb.getRemark(),

    // brand
    followedBrandName: pb.getFollowedBrandName(),
    followedBrandPic: pb.getFollowedBrandPic(),

    // brand_stat
    fansCount: pb.getFansCount(),
    adminCount: pb.getAdminCount(),
    publishActivityCount: pb.getPublishActivityCount(),
    spokesmanCount: pb.getSpokesmanCount(),
    endorseRequestToAuditCount: pb.getEndorseRequestToAuditCount(),
  };
};

export const listBrandFollowWithBrandAndBrandStats = async (
  userId: string,
  pager: PageParams
): Promise<PagedList<BrandFollowWithBrandAndBrandStat>> => {
  const cl = getBgsBrandFollowOpSafely();
  const req = new brand_followpb.ListBrandFollowWithBrandAndBrandStatsRequest();

  req.setLimit(pager.limit);
  req.setOffset(pager.offset);
  req.setUserId(Number(userId));

  return new Promise((resolve, reject) => {
    cl.listBrandFollowWithBrandAndBrandStats(
      req,
      getMetadata(),
      getOptionsOfLight(),
      (err, res) => {
        if (!isNull(err)) {
          reject(wrapperGrpcError(err.details));
          return;
        }
        const opRet = res.getOpRet()!;
        if (!opRet.getSuccess()) {
          reject(wrapperGrpcError(opRet.getMsg()));
          return;
        }
        const ret: PagedList<BrandFollowWithBrandAndBrandStat> = {
          total: 0,
          items: [],
        };
        ret.total = res.getTotal();
        ret.items = res
          .getBrandFollowWithBrandAndBrandStatsList()
          .map((u) => brandFollowWithBrandAndBrandStatPbToObject(u));
        resolve(ret);
      }
    );
  });
};
